home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / ansi / xflash1.zip / XFLASH-2.ASM < prev    next >
Assembly Source File  |  1987-03-17  |  11KB  |  435 lines

  1. ; XFLASH-2 by David Hite     -    Optimized for 8088-2 Processor
  2. ; Eliminates the flash that occurs during scrolling on the CGA.
  3. ; XFLASH is FreeWare.
  4.  
  5. ; Your machine may be able to move more characters or fewer
  6. ; characters during vertical retraces than mine (a Leading Edge Model M).  
  7. ; You can experiment by changing the values of max_vert and clr_max_vert.
  8. ; Max_horiz will probably not need to be changed, because it is
  9. ; based on the CGA's 200 scan lines.
  10.  
  11. ; The difference between XFLASH and XFLASH-2, other than the different
  12. ; values for max_vert and clr_max_vert, is that XFLASH-2 moves a word
  13. ; during the horizontal retrace, while XFLASH can only move a byte.
  14. ; The code is therefore slightly different.
  15.  
  16. ; for the Leading Edge Model M 8088-2 chip, the values are as follows
  17. ; clr_max_vert equ 500
  18. ; max_vert     equ 240
  19.  
  20.  
  21. clr_max_vert    equ    500        ; the maximum number of words to
  22.                         ; clear during a vertical retrace
  23. max_vert        equ    240        ; the maximum number of words to move in 
  24.                         ; a vertical retrace
  25. max_horiz    equ    197        ; the maximum number of horizontal retraces
  26.                         ; to be used for moving 1 word between 
  27.                         ; vertical retraces.  This is set to just
  28.                         ; less than the number of scan lines so that
  29.                         ; the next vertical retrace is not missed.  
  30.                         ; Increasing this value can actually slow the
  31.                         ; program down because it will have to wait
  32.                         ; longer for the next vertical retrace.
  33.  
  34. vstat        equ    3dah            ; the video status register
  35. v_retrace    equ    00001000b        ; vertical retrace bit mask
  36. h_retrace    equ    00000001b        ; horizontal retrace bit mask
  37.  
  38.  
  39. cseg    segment para public 'code'
  40.     assume cs:cseg,ds:cseg,ss:cseg,es:nothing
  41.     org    100h
  42.  
  43. start:
  44.     jmp install                ; install the program
  45.  
  46. savestack    dw    0,0
  47. request        dw    0            ; ax from interrupt
  48. fill_attrib    dw    0            ; bx from interrupt
  49. video_handler dd    0            ; address of the original video handler
  50. apage        db    0            ; active video page
  51. amode        db    3            ; active video mode
  52. display_seg     dw     0b800h        ; addr of cga display memory
  53.  
  54. new_video_int proc far            ; far label since it's entered by interrupt
  55.                             ; and thus must generate inter-segment ret
  56.     sti                        ; enable interrupts
  57.  
  58.     cmp    ah,0                    ; check for mode switch
  59.     jne    chk_mode
  60.     mov    cs:amode,al            ; remember new mode
  61.     jmp    short not_ours            ; and let bios change the mode
  62.  
  63. chk_mode:
  64.     cmp    cs:amode,3            ; we don't scroll graphics modes
  65.     jg    not_ours
  66.  
  67. chk_5:
  68.     cmp    ah,5                    ; check for page switch
  69.     jl    not_ours
  70.     jne    chk_6
  71.     mov    cs:apage,al            ; remember new page number
  72.     jmp    short not_ours            ; and let bios change the page
  73.  
  74. chk_6:
  75.     cmp    ah,6
  76.     jne    chk_7
  77. chk_6a:
  78.     cmp    cl,0                    ; we do it only for complete lines
  79.     jne    not_ours
  80.     cmp    dl,79
  81.     jne    not_ours
  82.     jmp    short scroll
  83.  
  84. chk_7:
  85.     cmp    ah,7
  86.     je    chk_6a
  87.  
  88. not_ours:
  89.     pushf                ; emulate int instruction
  90.     call dword ptr    [cs:video_handler]
  91.     iret
  92.  
  93. scroll:
  94.     mov cs:savestack,sp
  95.     mov cs:savestack+2,ss
  96.  
  97.     mov    cs:request,ax
  98.     mov    ax,cs
  99.     mov    ss,ax
  100.     mov    sp,100h
  101.  
  102.     push bp                ; set up a stack frame
  103.     mov    bp,sp
  104.     sub    sp,0eh
  105.     call savereg
  106.     mov    ds,ax
  107.     mov    ax,request
  108.  
  109.     call    main                ; that's where the work is done
  110.  
  111.     call restreg
  112.      add    sp,0eh
  113.     pop    bp
  114.  
  115.     mov ss,cs:savestack+2
  116.     mov sp,cs:savestack
  117.  
  118.     iret                ; return from interrupt
  119.  
  120. new_video_int    endp
  121.  
  122. inside proc near
  123. fix_ch0:
  124.     mov    ch,0
  125.     jmp    short chk_dh
  126. fix_ch24:
  127.     mov    ch,24
  128.     jmp    short chk_dh
  129. fix_dh0:
  130.     mov    dh,0
  131.     jmp    short chk_al
  132. fix_dh24:
  133.     mov    dh,24
  134.     jmp    short chk_al
  135. fix_al25:
  136.     mov    al,25
  137.     jmp    short regs_ok
  138.  
  139. main:
  140.     mov    fill_attrib,bx        ; save fill attribute for much later (clr_area)
  141.     push    dx                ; because MUL uses it
  142.     cmp    ch,0
  143.     jl    fix_ch0
  144.     cmp    ch,24
  145.     jg    fix_ch24
  146. chk_dh:
  147.     cmp    dh,0
  148.     jl    fix_dh0    
  149.     cmp    dh,24
  150.     jg    fix_dh24
  151. chk_al:
  152.     mov    ax,request
  153.     cmp    al,0
  154.     jle    fix_al25
  155.     cmp    al,25
  156.     jg    fix_al25
  157. regs_ok:
  158.     mov    request,ax        ; in case we fixed it
  159.     xor    bh,bh
  160.     mov    bl,apage            ; get the current page number
  161.     mov    ax,4096            ; the size of a a page
  162.     mul    bx                ; multiply by the page number to get offset
  163.     mov    di,ax            ; and put it in the destination index
  164.                         ; now calculate the offset of the window
  165.     mov    bl,ch            ; by getting the starting row
  166.     xor    bh,bh
  167.     mov    ax,160            ; we only handle full rows
  168.     mul    bx                ; and multiply by chars/row to get offset
  169.     add    di,ax            ; and adding to di to get address
  170.     mov    ax,di
  171.     mov    si,ax            ; and put it in the source index as well
  172.     pop    dx
  173.     mov    ax,request        ; get the original request
  174.     mov    bh,dh            ; move bottom line to bh
  175.     sub    bh,ch            ; subtract top line
  176.     inc    bh                ; bh now has number of lines in window
  177.  
  178.     cld                    ; we'll move forward unless scroll is down
  179.     mov    es,display_seg
  180.     cmp    al,0                ; clear the area?
  181.     jbe    m_1                ; yes
  182.     cmp    al,bh
  183.     je    m_1b                ; we are clearing all the lines
  184.     jb    m_2                ; we are clearing some of the lines
  185. m_1:                    ; we are clearing more than all the lines!
  186.     mov    al,bh            ; move number of lines in window to al
  187.     mov    request,ax
  188. m_1b:
  189.     jmp    clr_area
  190.  
  191. m_2:                    ; bh has lines in window, al has lines
  192.                         ; to scroll
  193.     cmp    ah,6                ; up or down?
  194.     je    up
  195. down:                    ; we are scrolling down
  196.     std                    ; so we move backwards
  197.  
  198.     sub    al,bh            ; the source is bh-al lines below si
  199.     neg    al                ; correct the sign
  200.     cbw                    ; convert to a word
  201.     mov    cx,160
  202.     mul    cx                ; multiply by chars/row
  203.     sub    ax,2                ; subtract a word to get end of line
  204.     add    si,ax            ; and add to si, the address of the up left
  205.  
  206.     ; the destination is the lower right which is bh lines 
  207.     ; below current di => di = di + bh*160 - 2
  208.  
  209.     mov    al,bh            ; get lines in window into al
  210.     cbw
  211.     mov    cx,160
  212.     mul    cx
  213.     sub    ax,2                ; subtract a word to get end of line
  214.     add    di,ax            ; di now has address of destination
  215.     
  216.     jmp    short movem
  217.  
  218. up:                        ; we are scrolling up
  219.     ; the source is al lines below si which is al*160 chars below current si
  220.  
  221.     cbw                    ; gets number of lines into ax
  222.     mov    cx,160
  223.     mul    cx
  224.     add    si,ax            ; si now has address of source
  225.  
  226.     ; the initial destination is correct, we don't need to change it
  227.  
  228. movem:                    ; now start to move words
  229.     ; fix bx such that it is number of words to move 
  230.     ; = (number of lines in window minus number of lines to scroll)*80
  231.  
  232.     mov    ax,request        ; get number of lines to scroll
  233.     cbw                    ; slightly faster than xor ah,ah
  234.     sub    al,bh            ; subtract lines in window from lines to scroll
  235.     neg    al                ; after correcting the sign, ax has lines to move
  236.     mov    cx,80            ; words/line
  237.     mul    cx                ; multiply to get words to move
  238.     mov    bx,ax            ; bx now has number of words to move
  239.  
  240.     push    ds                ; we're about to change it to display_seg
  241.     mov    dx,vstat            ; the video status register
  242.     mov    ds,display_seg        ; load address of display segment
  243.  
  244. mvm_vert:                ; first wait for a vertical refresh
  245.     mov    cx,bx            ; move words remaining to cx
  246.     cmp    cx,max_vert        ; too  many?
  247.     jle    mvm_many            ; no, go move'm
  248.     mov    cx,max_vert        ; yes, move max_vert more, maximum
  249. mvm_many:
  250.     sub    bx,cx            ; that many will remain when rep movsw ends
  251.  
  252. mvm_v_refresh:
  253.     in    al,dx
  254.     test    al,v_retrace
  255.     jnz    mvm_v_refresh        ; wait for a non retrace period
  256.  
  257. mvm_v_wait:
  258.     in    al,dx            ; get the retrace status
  259.     test    al,v_retrace        ; check for retrace in progress
  260.     jz    mvm_v_wait        ; wait until retrace
  261.  
  262.     ; in a vertical retrace, we can move many
  263.     rep    movsw
  264.     cmp    bx,0
  265.     je    mvm_end
  266.  
  267.     mov    cx,max_horiz
  268. mvm_1:
  269.     dec    bx
  270. mvm_h_refresh:
  271.     in    al,dx
  272.     test    al,h_retrace
  273.     jnz    mvm_h_refresh        ; wait for a non retrace period
  274.  
  275. ;    the next statement is commented out to prevent comm char loss 
  276. ;    cli                    ; disable interrupts while waiting (not long)
  277. mvm_h_wait:
  278.     in    al,dx            ; get the retrace status
  279.     test    al,h_retrace        ; check for retrace in progress
  280.     jz    mvm_h_wait        ; wait until retrace
  281.  
  282.     movsw                ; now move one word
  283. ;    sti                    ; and now enable interrupts again
  284.  
  285.     cmp    bx,0                ; are we finished?
  286.     je    mvm_end
  287.     loop    mvm_1
  288.     cmp    bx,0
  289.     je    mvm_end
  290.  
  291. mvm_do_cx_again:
  292.     mov    cx,bx            ; move words remaining to cx
  293.     cmp    cx,max_vert        ; too  many?
  294.     jle    mvm_h_many        ; no, go move'm
  295.     mov    cx,max_vert        ; yes, move max_vert more, maximum
  296. mvm_h_many:
  297.     sub    bx,cx            ; that many will remain when rep movsw ends
  298.     jmp    mvm_v_wait
  299.  
  300. mvm_end:                    ; we've finished moving
  301.     pop    ds                ; restore the data segment
  302.  
  303. clr_area:
  304. ;